﻿//-----------------------------------------------------------------------
// <copyright file="FxCopProjectFile.cs">
//     Copyright (c) Nicole Calinoiu. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Xml;
using System.Xml.Linq;

using Microsoft.FxCop.Sdk;

namespace Bordecal.FxCop.Sdk.Testing
{
	[SuppressMessage("Microsoft.StyleCop.CSharp.ReadabilityRules", "SA1116:SplitParametersMustStartOnLineAfterDeclaration",
		Justification = "Spacing in this class is intended to reflect XML element nesting.")]
	[SuppressMessage("Microsoft.StyleCop.CSharp.ReadabilityRules", "SA1118:ParameterMustNotSpanMultipleLines",
		Justification = "Spacing in this class is intended to reflect XML element nesting.")]
	[SuppressMessage("Microsoft.StyleCop.CSharp.DocumentationRules", "SA1600:ElementsMustBeDocumented",
		Justification = "False positive.")]
	internal static class FxCopProjectFile
	{
		internal static string Create(IEnumerable<string> ruleFiles, IEnumerable<string> targetFiles, IEnumerable<IConfigurableRule> ruleConfigurations)
		{
			XDocument document = new XDocument(new XDeclaration("1.0", "utf-8", "yes"));
			document.Add(new XElement("FxCopProject",
								new XAttribute("Version", "1.36"),
								new XAttribute("Name", "Temporary test project"),
							FxCopProjectFile.CreateProjectOptionsElement(),
							FxCopProjectFile.CreateTargetsElement(targetFiles),
							FxCopProjectFile.CreateRulesElement(ruleFiles, ruleConfigurations),
							new XElement("FxCopReport",
								new XAttribute("Version", "1.36"))));

			string fileName = Path.GetTempFileName();
			document.Save(fileName);

			return fileName;
		}

		private static XElement CreateProjectOptionsElement()
		{
			return new XElement("ProjectOptions",
							new XElement("SharedProject", "False"),
							new XElement("Stylesheet",
								new XAttribute("Apply", "False"),
								@"c:\program files\microsoft fxcop 1.36\Xml\FxCopReport.xsl"),
							new XElement("SaveMessages",
								new XElement("Project",
									new XAttribute("Status", "Active, Excluded"),
									new XAttribute("NewOnly", "False")),
								new XElement("Report",
									new XAttribute("Status", "Active"),
									new XAttribute("NewOnly", "False"))),
							new XElement("ProjectFile",
								new XAttribute("Compress", "True"),
								new XAttribute("DefaultTargetCheck", "True"),
								new XAttribute("DefaultRuleCheck", "True"),
								new XAttribute("SaveByRuleGroup", string.Empty),
								new XAttribute("Deterministic", "True")),
							new XElement("EnableMultithreadedLoad", "True"),
							new XElement("EnableMultithreadedAnalysis", "True"),
							new XElement("SourceLookup", "True"),
							new XElement("AnalysisExceptionsThreshold", 10),
							new XElement("RuleExceptionsThreshold", 1),
							new XElement("Spelling",
								new XAttribute("Locale", "en-US")),
							new XElement("OverrideRuleVisibilities", "False"),
							new XElement("CustomDictionaries",
								new XAttribute("SearchFxCopDir", "True"),
								new XAttribute("SearchUserProfile", "True"),
								new XAttribute("SearchProjectDir", "True")),
							new XElement("SearchGlobalAssemblyCache", "False"),
							new XElement("DeadlockDetectionTimeout", 120),
							new XElement("IgnoreGeneratedCode", "True"),
							new XElement("TargetFrameworkVersion", "3.5"));
		}

		private static XElement CreateTargetsElement(IEnumerable<string> targetFiles)
		{
			return new XElement("Targets",
							from f in targetFiles
							select new XElement("Target",
										new XAttribute("Name", f),
										new XAttribute("Analyze", "True"),
										new XAttribute("AnalyzeAllChildren", "True")));
		}

		private static XElement CreateRulesElement(IEnumerable<string> ruleFiles, IEnumerable<IConfigurableRule> ruleConfigurations)
		{
			return new XElement("Rules",
						new XElement("RuleFiles",
							from f in ruleFiles
							select new XElement("RuleFile",
										new XAttribute("Name", f),
										new XAttribute("Enabled", "True"),
										new XAttribute("AllRulesEnabled", "True"))),
						new XElement("Groups"),
						FxCopProjectFile.CreateSettingsElement(ruleConfigurations));
		}

		private static XElement CreateSettingsElement(IEnumerable<IConfigurableRule> ruleConfigurations)
		{
			XElement result = new XElement("Settings");
			if (ruleConfigurations != null)
			{
				using (XmlWriter writer = result.CreateWriter())
				{
					foreach (IConfigurableRule rule in ruleConfigurations)
					{
						writer.WriteStartElement("Rule");
						writer.WriteAttributeString("TypeName", rule.GetType().Name);

						rule.SaveSettings(writer);

						writer.WriteEndElement();
					}
				}
			}

			return result;
		}
	}
}